//
// Created by 袁绪龙 on 2024/4/25.
//

#include "AXBOpenGLWidget.h"
#include "qdebug.h"

namespace opengl1{

// 创建VBO和VAO对象
    unsigned int VBO, VAO;
/// 链接着色器的对象
    unsigned int shaderProgram;

/// 顶点着色器的位置数据
    float vertices[] = {
            -0.5F, -0.5F, 0.0F,
            0.5F, -0.5F, 0.0F,
            0.0F, 0.5F, 0.0F
    };

// 顶点着色器
    const char *vertexShaderSource = "#version 330 core\n"
                                     "layout (location = 0) in vec3 aPos;\n" "void main()\n"
                                     "{\n"
                                     " gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);\n"
                                     "}\0";

// 片元着色器
    const char *fragmentShaderSource = "#version 330 core\n"
                                       "out vec4 FragColor;\n"
                                       "void main()\n"
                                       "{\n"
                                       " FragColor = vec4(1.0f, 0.5f, 0.2f, 10.f);\n" "}\n\0";

}

AXBOpenGLWidget::AXBOpenGLWidget(QWidget *parent) {}

void AXBOpenGLWidget::initializeGL() {
    qDebug() << "initializeGL";
    // 初始化opengl - 不初始化就使用不了opengl
    initializeOpenGLFunctions();

    // VBO和VAO对象赋予ID
    glGenVertexArrays(1, &opengl1::VAO);
    glGenBuffers(1, &opengl1::VBO);

    // 绑定VBO和VAO对象
    glBindVertexArray(opengl1::VAO);
    glBindBuffer(GL_ARRAY_BUFFER, opengl1::VBO);

    // 为当前绑定到target的缓冲区对象创建一个新的数据存储
    // 如果data不是NULL，则使用来自此指针的数据初始化数据存储
    glBufferData(GL_ARRAY_BUFFER, sizeof(opengl1::vertices), opengl1::vertices, GL_STATIC_DRAW);

    /// 告知显卡如何解析缓冲里的属性值 -> 用途是为顶点设定属性指针。
    //0：这是指的顶点属性的位置。在着色器中你需要用 layout(location = 0) 来设置它的位置。
    //3：指定顶点属性的大小。你的顶点属性是一个vec3，所以它包含3个值。因此这里的大小是3。
    //GL_FLOAT：指定数据的类型，这里是GL_FLOAT，也就是浮点型。
    //GL_FALSE：定义了我们是否希望数据被标准化。这里把它设置为GL_FALSE。
    //3 * sizeof(float)：这个是步长。由于每个顶点的属性连续排列，我们直接按照顶点属性的大小032B跨过它们就可以。
    //(void*) 0：这是位置数据在缓冲中起始的位置。因为我们从头开始，所以这里是0。
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float),  (void*) 0);
    // 开启VAO管理的第一个属性值
    glEnableVertexAttribArray(0);

    // 用完就清空下绑定
    glBindBuffer(GL_ARRAY_BUFFER, 0);
    glBindVertexArray(0);

    // 加载顶点着色器
    unsigned int vertexShader = glCreateShader(GL_VERTEX_SHADER);
    glShaderSource(vertexShader, 1, &opengl1::vertexShaderSource, nullptr);
    glCompileShader(vertexShader);
    // 加载片元着色器
    unsigned int fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(fragmentShader, 1, &opengl1::fragmentShaderSource, nullptr);
    glCompileShader(fragmentShader);
    // 链接着色器 - 用glLinkProgram链接，然后用glUserProgram使用
    opengl1::shaderProgram = glCreateProgram();
    glAttachShader(opengl1::shaderProgram, vertexShader);
    glAttachShader(opengl1::shaderProgram, fragmentShader);
    glLinkProgram(opengl1::shaderProgram);
    // 链接上之后把两个着色器删除
    glDeleteShader(vertexShader);
    glDeleteShader(fragmentShader);

}

void AXBOpenGLWidget::resizeGL(int w, int h) {
}

void AXBOpenGLWidget::paintGL() {
    qDebug() << "paintGL";
    glClearColor(0.2F, 0.3F, 0.3F, 1.0F);
    glClear(GL_COLOR_BUFFER_BIT);

    glUseProgram(opengl1::shaderProgram);
    glBindVertexArray(opengl1::VAO);
    glDrawArrays(GL_TRIANGLES, 0, 3);
}
